.TITLE DCWOP - Write operations .IDENT /05.00/ .IF DF D$$CHE ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; ; Previously modified by: ; ; J. Kauffman 10-DEC-87 02.00 ; L.B.McCulley 31-Dec-91 4.00 ; D. Carroll 27-July-1992 4.01 ; L. B. McCulley 8-Aug-1992 4.01a ; D. Carroll 8-October-1992 4.02 ; D. Carroll 30-October-1992 4.03 ; D. Carroll 12-Nov-1992 4.04 ; D. Carroll 21-Nov-1992 4.05 ; D. Carroll 01-May-1995 4.06 ; ; Modified for RSX-11M-PLUS V4.6 by: ; ; D. Carroll 8-Jan-1996 05.00 ; DC430 -- Modified to handle 32-bit LBNs ; ; ; ; Disk Data Caching Write functionality ; ; See module DCCHE,DCROP for a complete description of write ; interactions with disk data caching. ; ;- .MCALL F11DF$ F11DF$ ; Define window block offsets .PSECT DC$WOP, RO, I .SBTTL Write Phase-I .SBTTL + DCW1 - Write operations ;+ ; **-DCW1- Write operations, Phase I ; ; Passed: ; UCBX mapped ; ; R1 -> I/O packet ; I.EFN := Indicates if I/O is virtual ; I.TCB -> TCB of requesting task ; T.ST3 := T3.ACP indicates I/O is from an ACP ; I.PRM+P2 := Size of request in bytes ; R5 -> UCB ; ; Returned: ; All writes require some processing in cache, so: ; C-CLR returned to tell $DRQRQ not to forward to driver ; $DRQRQ called to explicitly queue packet to driver with cacher IOC ; (always goes to driver bypassing cache if cacher is mapped) ; ; Action: ; All extents involved will be acted upon no matter what ; behaviour attributes have been selected for the device. ; ; If exactly one extent maps the request then it will be "locked down" ; and the driver invoked through $DRQRQ. The internal IOC will transfer ; data to cache when the write completes successfully. ; ; Otherwise all involved extents will be deleted and the driver invoked ; via $DRQRQ. A placeholder CED is retained in cache to close a race ; window with possible overlapping read-aheads from cache. ; ; All asynchronous I/O is serialized by using the attachment queue to ; the CED and the cache Phase 2 processing. ; ; ; Notes: ; I/O operations which specify the bypass bits must still ; update the cache, for the benefit of other non-bypass ; readers. Keep in mind that IQ.UMD (user-mode diagnostic) ; requests use parameter 6 to specify the diagnostic buffer ; address. Therefore, the cache can only use parameter 3 ; if it really has to. ; DCW1:: CLRB I.PRM+P3+1(R1) ; initialize the high byte CALL INICTX ; Initialize context BCC COMMON ; if CC, not virtual I/O TST $DCCEL ; extent info valid? BEQ COMMON ; if EQ, nope, don't bother CALL CLCLEN ; determine size to check caching CMPB R4,@2(R0) ; is the request too large? BHI COMMON ; too big, can't defer this extent BITB #XC.DFR,APR6.BASE+X.CSTS ; are deferred extents allowed .IF DF CHEWBH BNE 10$ ; if NE, process deferred option BITB #X2.WBH,APR6.BASE+X.CST2 ; is write-behind allowed .ENDC ;DF,CHEWBH BEQ COMMON ; if EQ, nope, finish up ; ; if bypass bits set in write subfunction, ; purge cache of any affected extents ; and pass request to driver ; 10$: BIT #CHEBYP, I.FCN(R1) ; any bypass bits set? BNE COMMON ; yes, can't cache such BIT #777,I.PRM+P2(R1) ; partial block transfer? BNE COMMON ; yes, can't cache such MOVB $DCSTS,I.PRM+P3+1(R1) ; save the extent status byte .IF DF CHEWBH BICB #^C,I.PRM+P3+1(R1) ; isolate all but deferred sts BNE COMMON ; if NE, yes, don't invoke WBH BITB #X2.WBH,APRD.BASE+X.CST2 ; are write behind operations legal BEQ COMMON ; if EQ, nope, just use deferred .IF DF P$$CTL ;DC430 CMP $PRISZ,#1000. ; enough space for write-behind? ;DC430 BLO COMMON ; if LO, nope, skip it ... ;DC430 .ENDC ;DF,P$$CTL ;DC430 ;DC430 BISB #,I.PRM+P3+1(R1) ; flag for deferred path .ENDC ;DF,CHEWBH COMMON: CLR $DCCEL ; invalidate previous status MOV 4(R0),R0 ; extract the statistics address MP.PAR ; map cache par for GETCRP CALL GETCRP ; get cache request packet for BCC 40$ ; ... local context storage 20$: CALLR CHEPUR ; clean out overlapping extents ; got Cache Request Packet, go ahead 40$: MOVB I.PRM+P3+1(R1),R.LBNL(R2) ; save deferred status flag CLRB I.PRM+P3+1(R1) ; and reset flag to zero MOV R0,R.STAT(R2) ; Set statistics context in CRP USTAT$ S.WTOT ; Increment write total CALLR Q2PHS1 ; queue the packet to phase II .SBTTL + DCW2 - Phase 2 entry, test deferred writes ;+ ; **-DCW2- Write Phase II entry ; ; Request here is eligible for cache processing (eg, no bypass) ; ; Deferred writes? ; ; This section checks to see if the I/O request is virtual and it is for ; a temporary file; i.e. WS.MDL is set in window status. ; ; If so, it should be deferred if possible so search for an existing extent ; ; If none is found, dispatch to create a new CED. ; If any existing extent is found, it is tested for partial overlap condition ; ; If exactly one extent completely contains the range of the request, the ; transfer is performed within that extent. ; ; Any partially overlapping extents are purged to disk, and after all such ; extents purge successfully, a new CED is created to complete the requeue ; Failure to allocate a buffer for the extent will cause a write to disk. ; ; Input: ; R1 - URP ; R5 - UCB ; UCBX mapped ;- DCW2:: MP$PAR ; map cache partition MOV I.CRP(R1),R2 ; Get CRP pointer MOV R.LBNL(R2),-(SP) ; Save flag for I/O request deferred MP.UCBX ; map the UCBX again CALL SEARCH ; Locate first overlapping extent BIT #WS.MDL,(SP)+ ; Is I/O request deferred? BNE DEFER ; NE, yes, go process it BCS MISS ; SEARCH found no extent, process miss .SBTTL HIT - Process a non-deferred extent cache hit ;+ ; **-HIT- Process a non-deferred extent cache hit ; ; This routine will determine if a single extent overlaps a given ; write request, and if so, will update the cache data after I/O is ; completed. If a miss is declared, we still must have a placeholder ; CED to insure that data cache read-ahead is interlocked with other ; requests. ; ; Input: ; R0 - CED with overlap ; R1 - URP ; R2 - LSP of highest requested LBN (from SEARCH) ; R3 - MSP of highest requested LBN (from SEARCH) ; R4 - Size of request in blocks (from SERACH) ; R5 - UCB address ; ; Cache partition mapped ; ; Output: ; If the request is handled by a single extent, it will ; be queued to disk, and updated at I/O completion, otherwise ; all overlapping extents will be purged, and the request ; forwarded to disk. ;- HIT: BIT #CHEBYP,I.FCN(R1) ; are we bypassing cache? BNE 20$ ; yes, flush cache here BIT #777,I.PRM+P2(R1) ; odd block transfer? BNE 20$ ; yes, purge it out ... CMP R3, E.LBNH+2(R0) ; Might this extent fully map request ;DC430 BLO 10$ ; If LO, yes ;**-1 BHI 20$ ; If HI, no, flush it out CMP R2, E.LBNH(R0) ; Double word comparison BHIS 20$ ; If HIS, no, flush it 10$: MOV I.PRM+P4(R1),-(SP) ; extract the logical block ;DC430 BIT #DV.32B,U.CW1(R5) ; using 32-bit LBNs ;DC430 BNE 11$ ; if NE, yes, continue ;DC430 ;DC430 CLRB 1(SP) ; clean off the high stuff ;DC430 ;DC430 11$: CMP (SP)+, E.LBNL+2(R0) ; Does this truely map it ;DC430 BHI 40$ ; If HI, yes ;**-1 BLO 20$ ; If LO, no, flush it out CMP I.PRM+P5(R1), E.LBNL(R0) ; Double word comparison BHIS 40$ ; If HIS, yes, ok ; if LO, no, flush it 20$: USTAT$ S.WLAP ; Increment partial overlap count CALL DELATT ; delete any overlapping extents BCC MISS ; ok, they're gone ; we're queued to CED for phase 30$: RETURN ; CED unbusy queues us for Phase 40$: CALL ATTCED ; attach to extent, queue if busy BCS 30$ ; busy, just return BISB #ES.WIP,E.STAT(R0) ; attached ok, show why CED busy USTAT$ S.WHIT ; Increment write hit stats BR DOWRIT ; finish off packet and do write .SBTTL + MISS - Process clean cache miss ;+ ; ; MISS found no extent in cache covering request LBN range ; so we must create a placeholder CED for duration of I/O ; ; Input: ; R1 - URP ; R4 - Size of request ; R5 - UCB address of issuing device ; ; Output: ; Placeholder CED created, and request forwarded ; on to the driver for processing. The placeholder will be ; deleted when the I/O is completed. ; ;- MISS: CALL CRECED ; allocate a CED for placeholder BCC 20$ ; got it ok, now use it CALL FREAGE ; try to free one for use now BCC MISS ; did free one, now use it TST R0 ; did we get a CED from FREAGE? BEQ 10$ ; if EQ, nope, just requeue to phase II CALLR ATTCED ; attach to the CED with outstanding I/O 10$: CALLR Q2PHS1 ; else queue a retry to Phase 2 20$: CALL ATTCED ; attach to new CED, should always succeed ;+ ; Initialize the CED, with no memory buffer, no age list entry, ; just a specific LBN and size filled in ;- CLR E.PHYA(R0) ; ...no phys mem address CLR E.BNXT(R0) ; ...no memory buffer list entry CLR E.BPRV(R0) ; ... CLR E.ANXT(R0) ; ...no age list insertion CLR E.APRV(R0) ; ... MOV I.UCB(R1),E.UCB(R0) ; set UCB pointer for phase 2 BISB #,E.STAT(R0) ; set status flags to be ; write placeholder, write in progress, delete when done CALL SETLBN ; Set up LBN/size parameters CALL QINLBN ; insert into LBN queue of CEDs .SBTTL + DOWRIT, Issue write request to driver ;+ ; **-DOWRIT- Issue write request to driver ; ; Context: ; R0 -> CED for extent covering request ; R1 -> I/O request packet ; ; Finish preparing I/O packet and queue to driver for cacher ;- DOWRIT: MOV KINAR5, I.IOSB+2(R1) ; Load APR bias and address of IOC ;DC430 MOV #WRTIOC!1, I.IOSB+4(R1) ; I/O completion routine, note bit 0 ;**-2 CLRB I.EFN(R1) ; insure as logical I/O ; ; All changes to the user I/O packet will be restored ; from the Cache Request Packet before calling $IOFIN. ; CALLR .DRQRQ ; Issue disk I/O, IOC cleans up .SBTTL Deferred write processing .SBTTL + DEFER, Determine outcome of deferred request search DEFER: BCS 60$ ; CS, SEARCH found no extent, must load ;+ ; We found at least one extent, does it completely cover request? ; ; Context: ; Cache partition mapped ; ; R0 -> First overlapping extent ; R1 -> URP ; R2 := Least Significant Part (LSP) of the highest requested block ; R3 := Most Significant Part (MSP) ; R4 := Length of request in blocks ; R5 -> UCB ;- MOV I.PRM+P4(R1),-(SP) ; extract the LBN (msp) ;DC430 BIT #DV.32B,U.CW1(R5) ; device using 32-bit LBNs ;DC430 BNE 10$ ; if NE, yes, continue ;DC430 ;DC430 CLRB 1(SP) ; clean up the high stuff ;DC430 ;DC430 10$: CMP (SP)+,E.LBNL+2(R0) ; request begin before extent? ;DC430 BLO 50$ ; yes, overlap, flush it ;DC430 BHI 20$ ; no, extent might cover transfer ;DC430 CMP I.PRM+P5(R1),E.LBNL(R0) ; ..double precision.. ;**-3 BLO 50$ 20$: CMP R3,E.LBNH+2(R0) ; request end after extent? ;DC430 BHI 50$ ; yes, overlap, flush it ;**-1 BLO DFRCPY ; no, extent does cover transfer CMP R2,E.LBNH(R0) ; ..double precision.. BLO DFRCPY ; remember, E.LBNH is next block ;+ ; some extent overlaps, flush it out then process the transfer ;- 50$: USTAT$ S.WLAP ; tally a write that overlapped CALL DELATT ; delete all overlapping extents BCC 60$ ; ok, got them all ; we're queued to first one for IOC RETURN ; CED unbusy queues us for Phase II 60$: CALL GETBUF ; get an extent BCS MISS ; if CS, allocation failed, flag miss .SBTTL + DFRLOD - Create New Deferred Extent ;+ ; DFRLOD - invoked when a deferred write extent is detected after a ; total miss or complete purge of overlapping extents. ; ; Passed: ; R1 => I/O request packet from user ; R4 -> Size of request in blocks (gotten from SEARCH) ; R5 => UCB ; ; Mapped: Cache partition ; ; Action: ; link newly allocated extent into the CED lists ;- DFRLOD: USTAT$ S.WLOD ; tally a write that didn't hit .IF DF CHEWBH ; write behind support MOV I.CRP(R1),R2 ; get the CRP pointer BIT #WS.WBH,R.LBNL(R2) ; is this write behind activity? BEQ 10$ ; if EQ, nope, don't mark for delete BISB #ES.DEL,E.STAT(R0) ; flag as being marked for delete BICB #WS.WBH,R.LBNL(R2) ; don't need the flag anymore ... 10$: .ENDC ;DF,CHEWBH BISB #ES.WDF,E.STAT(R0) ; indicate deferred extent ;+ ; Initialize size of new CED from parameters in the I/O Block ;- CALL SETLBN ; set up our LBN/size parameters ;+ ; Now insert the initialized CED into the device and age queues ;- CALL QADAGE ; Insert the CED into the age li CALL QINLBN ; and into the unit LBN list .SBTTL + DFRCPY - Load Deferred Extent w/data ;+ ; DFRCPY - Deferred Write processing completion ; ; Passed: ; Cache partition mapped ; ; R0 -> CED of target extent (there is exactly one extent involved ; R1 -> User I/O Request Packet (URP, in primary pool for driver) ; I.PRM+P1 := Source buffer address ; I.PRM+P2 := Byte count ; I.PRM+P3 ; I.PRM+P5 := Requested LBN least significant part (LSP) ; I.CRP -> Cache Request Packet (CRP in cache pool) ; I.ACED -> CED of first extent involved ; R5 -> UCB ; ; Returned: ; N/A - control is passed to $IOFIN ; ; Action: ; Transfer data from user buffer into the deferred extent ; then set up and finish the I/O completion. ;- DFRCPY: CALL ATTCED ; attach the CED for extent BCS LATER ; it's busy already, queued to phase II USTAT$ S.WDFR ; tally a write that didn't hit disk BITB #ES.WDF,E.STAT(R0) ; already deferred? BNE 20$ ; yup, don't adjust sizes .IF DF CHEWBH MOV I.CRP(R1),R2 ; get the CRP into R2 BIT #WS.WBH,R.LBNL(R2) ; is this write behind BNE 20$ ; if NE, don't convert to DFR .ENDC ;DF,CHEWBH BISB #ES.WDF,E.STAT(R0) ; Indicate this CED now deferred CALL CLCLEN ; determine the toal request size CMPB R4,E.SIZE(R0) ; are they the same size? BEQ 20$ ; yes, don't worry, no adjustment BLO 10$ ; if LO, sanity prevails ... FATAL$ BE.IDC ; internal inconsistency ;+ ; Since we have just changed a CED from being normal to being ; deferred, we will shrink the size of the CED to be the same ; size as the request. This will tailor the request so that ; when the CED is written to disk, we will only write that which ; was actually deferred. ;- 10$: CALL SETLBN ; reset LBN/size parameters ;+ ; Input parameters to WRTXFR are: ; R0 := target CED address (set already) ; R1 := I/O request packet (set already) ;- 20$: CALL WRTXFR ; and do transfer to cache MOV I.ACED(R1),R0 ; restore CED address from pkt .IF DF CHEWBH MOV I.CRP(R1),R2 ; get the CRP pointer BIT #WS.WBH,R.LBNL(R2) ; is this a write behind? BEQ 40$ ; if EQ, nope, process deferred normally ;+ ; At this point, we need to create an I/O packet which will write out ; the affected portion of this CED, and then release the I/O pkt ;- MOV R1,-(SP) ; save R1 for now ... CALL DFRPKT ; create a packet BCS 30$ ; failed to allocate I/O packet MOV R1,R4 ; copy the packet for now ... MOV (SP),R2 ; restore original URP MOV I.PRM+P2(R2),I.PRM+P2(R4) ; update the length MOV I.PRM+P4(R2),I.PRM+P4(R4) ; update the target IOP ;DC430 BIT #DV.32B,U.CW1(R5) ; device support 32-bit LBNs? ;DC430 BNE 25$ ; if NE, yes, leave P4 as is ;DC430 CLRB I.PRM+P4+1(R4) ; zero out the high byte ;DC430 25$: MOV I.PRM+P5(R2),R1 ; get the LBN LSP ;DC430 MOV R1,I.PRM+P5(R4) ; and update the LBN LSP ;**-2 ;+ ; Since the CED will overlap, carry is allowed to be carried ; across, to create the correct offset ;- SUB E.LBNL(R0),R1 ; convert to an offset ASH #3,R1 ; convert to 32.wd offset ADD E.PHYA(R0),R1 ; compute the address for real MOV #APR6.BASE,R2 ; and start at the beginning CALL $MPPHY ; map address for NPR device MOV R4,E.IOPA(R0) ; show new packet as owner now ... MOV R0,I.ACED(R4) ; and let DETCED know intentions BISB #ES.WIP,E.STAT(R0) ; and show write in progress MOV R1,I.PRM+P1.1(R4) ; load in the high order bits MOV R2,I.PRM+P1.2(R4) ; and the low order bits MOV R4,R1 ; move back to usual register MOV @#KISAR6,-(SP) ; save mapping CALL .DRQRQ ; queue the I/O to disk, delayed MOV (SP)+,@#KISAR6 ; restore mapping for RLSCRP MOV (SP)+,R1 ; restore original URP CLR I.ACED(R1) ; no longer attached to CED BR 50$ ; and finish up now ... ;+ ; We failed to allocate an IOP, so we must forward to disk ;- 30$: MOV (SP)+,R1 ; restore URP address CALLR DOWRIT ; and forward to the driver ... .ENDC ;DF,CHEWBH 40$: CALL DETCED ; now release CED and 50$: CALL RLSCRP ; delete CRP, refresh URP ;+ ; This is a deferred write which has just completed. Since no disk I/O ; occurred, no status has been returned and must be faked back to the user ;- MOV R1, R3 ; Set packet address for $IOFIN MOV #IS.SUC&377,R0 ; Fake success status back to user MOV I.PRM+P2(R3),R1 ; Put in number of transferred bytes CALL $IOFIN ; Return I/O status to user LATER: CLC ; make sure $DRQRQ doesn't call RETURN ; to run Phase II ; successfully deferred write .SBTTL Write I/O completion .SBTTL + WRTIOC - Internal I/O completion routine ;+ ; **-WRTIOC- Process internal I/O completion for write request ; ; Passed: ; R3 -> Driver request packet ; I.UCB -> UCB ; I.PRM+P3, P4 := Driver status ; I.CRP(R3) -> Cache request packet (saved context from user request ; I.ACED(R3) -> CED of extent involved in this transfer ; ; Returned: ; N/A - status is passed back to user from driver packet returns ; via $IOFIN ; ; Action: ; If placeholder CED do not transfer data into cache, delete extent ; If error, do not transfer data into cache, delete extent ; If extent exists and no error, transfer data into cache extent ; Phase 2 will process all blocked requests queued to extent, FIFO ; ; Since we are being called from $IOFIN, let the driver continue ; execution, and we will finish the copy function once complete. ; Without calling fork, it would be possible for EBLXIO to call ; fork, and transfer control to another processor. This would cause ; the subsequent return to the driver to be executed on the wrong ; processor, or with a delay which could impact I/O throughput. ; ; In a non-mP environment, this call to fork will minimize the amount ; of pool required if EBLXIO is required to fork again. ; ;- WRTIOC: CALL $SAVNR ; save non-volitile registers MOV R3,R4 ; Copy I/O packet pointer ADD #I.PRM+12,R4 ; Point to last word for fork block MOV @#KINAR5,(R4) ; Load our bias MOV R1,-(R4) ; Store I/O status block contents MOV R0,-(R4) ; in standard P3,P4 of IOP .IF DF M$$PRO CLR I.PRM(R3) ; Set up our URM for FORK0 .ENDC CALL $FORK0 ; Fork here to allow driver completion SUB #I.PRM+4,R3 ; Point to beginning of I/O packet MOV R3,R1 ; set conventional register MOV I.ACED(R1),R0 ; get CED from URP MOV I.UCB(R1),R5 ; get UCB (and UCBX) for device MP.UCBX ; map UCB extension MOVB APR6.BASE+X.CST2,R3 ; save status flag from UCBX MP$PAR ; map cache partition BITB #CS.DBG,APRD.BASE+H.CSTS ; is debug enabled BEQ 7$ ; if EQ, nope ... CMP E.IOPA(R0),R1 ; is this packet for this ced? BNE 3$ ; no, go die ... CMP E.UCB(R0),R5 ; ucb match ced? BEQ 7$ ; ok, sanity checked 3$: FATAL$ BE.UCB ; UCB is inconsistent 7$: MOV I.CRP(R1),R2 ; get CRP pointer to MOV I.PRM+P3(R1),R.P3(R2) ; save status and MOV I.PRM+P4(R1),R.P4(R2) ; bytes transferred for user IOSB BITB #X2.DEA,R3 ; deactivating cache? BNE 10$ ; yes, skip transfer into cache ;+ ; Context: ; R0 -> CED ; R1 -> packet ;- BITB #ES.WPL,E.STAT(R0) ; placeholder CED? BNE 10$ ; yep, transfer impossible TSTB I.PRM+P3(R1) ; Is an error indicated? BPL 20$ ; If PL, no BISB #ES.ERR,E.STAT(R0) ; set error bit in CED status 10$: BISB #ES.DEL,E.STAT(R0) ; delete placeholder or error CED BR 30$ ; skip data transfer, release CED ;+ ; Input parameters to WRTXFR are: ; R0 := target CED address ; R1 := I/O request packet (just refreshed) ;- 20$: .IF DF CHEWBH BIT #WS.MDL,R.LBNL(R2) ; is this a write behind function BNE 30$ ; if NE, yes, don't copy buffer .ENDC ;DF,CHEWBH CALL RFRSHP ; refresh packet contents before xfr CALL WRTXFR ; do the transfer into cache extent MOV I.ACED(R1),R0 ; restore CED address from pkt MOV I.CRP(R1),R2 ; get CRP pointer from pkt 30$: BICB #ES.WIP,E.STAT(R0) ; clear write-in-progress flag CALL DETCED ; detach, requeue any waiting pkts CALL RLSCRP ; delete CRP after refreshing URP MOV R1,R3 ; set I/O pkt ptr for $IOFIN MOV I.PRM+P3(R3), R0 ; Get driver completion status MOV I.PRM+P4(R3), R1 CALL $IOFIN ; Return I/O completion and exit ;**-2 CALLR DCFORK ; via phase 2 dispatcher. .SBTTL Local Subroutines .SBTTL + DCFLSH - Deletes all involved extents ;+ ; Passed: ; Cache partition mapped ; ; R0 -> CED of first overlaping extent ; R2 := High LBN Least significant part (LSP) ; R3 := High LBN Most significant part (MSP) ; R5 := UCB address ; ; Returned: ; All registers preserved except R0 ; CC - All extents were able to be eliminated ; CS - At least one of the extents could not be eliminated ;- DCFLSH: CLR -(SP) ; Initialize status return 10$: MOV E.LNXT(R0),-(SP) ; save pointer to next CED TST E.IOPA(R0) ; is this CED busy? BNE 50$ CALL FRECED ; Delete this extent BCC 70$ ; IF CC, extent was eliminated BR 60$ ; 50$: BISB #ES.DEL,E.STAT(R0) ; busy, delete when owner detach 60$: MOV R0,2(SP) ; save last CED still flushing 70$: MOV (SP)+,R0 ; restore the next CED BEQ 90$ ; yep, exit CMP R3, E.LBNL+2(R0) ; Does this extent overlap the request ;DC430 BHI 10$ ; If HI, yes ;**-1 BLO 90$ ; If LO, no CMP R2, E.LBNL(R0) ; Double word comparison BHIS 10$ ; If HIS, yes 90$: TST (SP) ; did we have a CED still in pipe? BEQ 95$ ; if EQ, nope, leave R0-> next CED MOV (SP),R0 ; flag the last CED which was written 95$: ROL (SP)+ ; set the status for carry returned RETURN ; NOTE carry sets because cache ; addresses are all > 120000(8) ;+ ; **-DELATT- Delete all overlapping requests, and if pending I/O ; attach to queued CED ; ; Passed: ; Cache partition mapped ; ; R0 -> CED of first overlaping extent ; R2 := High LBN Least significant part (LSP) ; R3 := High LBN Most significant part (MSP) ; R5 := UCB address ; ; Returned: ; All registers preserved except R0 ; CC - All extents were able to be eliminated ; CS - At least one of the extents could not be eliminated ; request atteched to CED w/ pending I/O ;- DELATT::CALL DCFLSH ; delete all affected extents BCC 5$ ; queued (while deferred writes) ; phase 2 comes back here after CALL ATTCED ; queue to it SEC ; show we queued 5$: RETURN .SBTTL + WRTXFR - Transfer from user buffer to cache extent ;+ ; WRTXFR - transfer from a user buffer to a cache extent ; we know that there is exactly one single cache extent involved ; this is called from disk write internal ioc for real disk writes ; and to complete deferred write processing when the write was ; successfully deferred ; ; Entry: ; R0 => CED of target extent ; R1 => I/O packet containing user buffer info ; I.PRM+P2 = byte count ; I.PRM+P4 = requested LBN most significant part ; I.PRM+P5 = requested LBN least significant part ; ; R0, R1 is saved/restored, all other registers are trashed ; ; ; Prepare input parameters to $BLXIO: ; R0 := Byte count (I.PRM+P2) ; R1 := Source APR5 bias ; R2 := Source APR5 displacement ; R3 := Destination APR6 bias ; R4 := Destination APR6 displacement (140000) ;- WRTXFR: MOV R1, -(SP) ; Save packet address for return MOV R0, -(SP) ; and save the CED address BISB #ES.XIP,E.STAT(R0) ; flag that transfer is active CALL ADJBUF ; Converts to doubleword if device NPR MOV R0,R4 ; switch registers for convenience MOV R1,R0 MOV I.PRM+P1.1(R0), R1 ; get source APR bias for EBLXIO MOV I.PRM+P1.2(R0), R2 ; get source APR displacement... SUB #20000, R2 ; adjust for APR5 not APR6 ;+ ; The destination APR bias is the extent bias offset by the number of blocks ; between the requested LBN and the low LBN of the extent. ;- MOV I.PRM+P5(R0), R3 ; Get LSP of requested LBN SUB E.LBNL(R4), R3 ; Safe to assume carry available ASH #3, R3 ; Convert to 32-word blocks ADD E.PHYA(R4), R3 ; and include extent base address MOV #APR6.BASE, R4 ; set target APR displacement MOV I.PRM+P2(R0), R0 ; set byte count CALL EBLXIO ; Transfer the data. MOV (SP)+, R0 ; restore CED address as well BICB #ES.XIP,E.STAT(R0) ; flag transfer not in progress MOV (SP)+, R1 ; restore I/O packet address RETURN .ENDC ; .IFDF D$$CHE .END